<template>
  <!-- #ifndef APP-NVUE -->
  <view
    class="yingbing-flip"
    :prop="flipProp"
    :change:prop="flip.propWatcher"
    @touchstart="flip.touchstart"
    @touchmove="flip.touchmove"
    @touchend="flip.touchend"
    @touchcancel="flip.touchcancel"
    @mousedown="flip.mousedown"
    @mousemove="flip.mousemove"
    @mouseup="flip.mouseup"
    :style="{
		background: background,
		backgroundSize:backgroundSize
	}">
    <!-- #endif -->
    <!-- #ifdef APP-NVUE -->
    <view
      class="yingbing-flip"
      ref="yingbingFlip"
      @touchstart="fliptouchstart"
      @touchmove="fliptouchmove"
      @touchend="fliptouchend"
      :style="{
		background: background,
		backgroundSize:backgroundSize
	}">
      <!-- #endif -->
      <view
        class="yingbing-flip-item"
        :class="'yingbing-flip-item_' + item"
        v-for="(item, index) in dataSync"
        :ref="'yingbingFlipItem_' + item"
        :style="{
			'background': background,
			backgroundSize:backgroundSize,
			'transform': item > currentIndex ? translate + '(' + fullSize + ')' : item < currentIndex ? translate + '(-' + fullSize + ')' : ''
		}"
        :key="getKey(item)">
        <view
          class="yingbing-flip-item-content"
          :ref="'yingbingFlipItemContent_' + item"
          :class="'yingbing-flip-item-content_' + item"
          :style="{
				'background': background,
				backgroundSize:backgroundSize,
				'transform': item < currentIndex ? type == 'real' ?  translate + '(' + fullSize + ')' : translate + '(0)' : translate + '(0)'
			}">
          <!-- #ifdef MP -->
          <!-- 微信小程序vue2虽然支持在v-for中嵌套同名插槽，但会一直报错，引起页面卡顿，vue3不支持在v-for中嵌套同名插槽，所以增加2种微信小程序使用方式 -->
          <mp-child class="yingbing-flip-item-content" v-if="item > -1 && item < count && componentName"
                    :item="data[item]" :index="item" :componentName="componentName"></mp-child>
          <slot style="width: 100%;" v-if="item > -1 && item < count && !componentName" :name="'wx:' + item"
                :item="data[item]" :index="item"></slot>
          <!-- #endif -->
          <!-- #ifndef MP -->
          <slot v-if="item > -1 && item < count" :item="data[item]" :index="item"></slot>
          <!-- #endif -->
        </view>
        <view
          class="yingbing-flip-item-bg"
          :ref="'yingbingFlipItemBg_' + item"
          :class="'yingbing-flip-item-bg_' + item"
          :style="{
				background: background,
				transform: item < currentIndex && type == 'real' ?  translate + '(0)' : translate + '(' + fullSize + ')',
			}"></view>
        <view
          class="yingbing-flip-item-shadow"
          :ref="'yingbingFlipItemShadow_' + item"
          :class="'yingbing-flip-item-shadow_' + item"
          :style="[shadowStyle]"></view>
      </view>
      <view class="yingbing-flip-pulldown"
            :style="[pulldownStyle]" v-if="pulldownable" ref="yingbing_flip_pulldown">
        <view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-default" ref="yingbing_flip_pulldown_default">
          <slot name="pulldownDefault"></slot>
        </view>
        <view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-ready" ref="yingbing_flip_pulldown_ready">
          <slot name="pulldownReady"></slot>
        </view>
        <view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-loading" ref="yingbing_flip_pulldown_loading">
          <slot name="pulldownLoading"></slot>
        </view>
        <view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-success" ref="yingbing_flip_pulldown_success">
          <slot name="pulldownSuccess"></slot>
        </view>
        <view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-fail" ref="yingbing_flip_pulldown_fail">
          <slot name="pulldownFail"></slot>
        </view>
      </view>
      <view class="yingbing-flip-pullup"
            :style="[pullupStyle]" v-if="pullupable" ref="yingbing_flip_pullup">
        <view class="yingbing-flip-pullup-item yingbing-flip-pullup-default" ref="yingbing_flip_pullup_default">
          <slot name="pullupDefault"></slot>
        </view>
        <view class="yingbing-flip-pullup-item yingbing-flip-pullup-ready" ref="yingbing_flip_pullup_ready">
          <slot name="pullupReady"></slot>
        </view>
        <view class="yingbing-flip-pullup-item yingbing-flip-pullup-loading" ref="yingbing_flip_pullup_loading">
          <slot name="pullupLoading"></slot>
        </view>
        <view class="yingbing-flip-pullup-item yingbing-flip-pullup-success" ref="yingbing_flip_pullup_success">
          <slot name="pullupSuccess"></slot>
        </view>
        <view class="yingbing-flip-pullup-item yingbing-flip-pullup-fail" ref="yingbing_flip_pullup_fail">
          <slot name="pullupFail"></slot>
        </view>
      </view>
    </view>
</template>
<script>
  // #ifdef APP-NVUE
  import flipBindingx from './flip_bindingx.js';
  // #endif
  // #ifdef MP
  import MpChild from './mpChild.vue';
  // #endif
  export default {
    // #ifdef APP-NVUE
    mixins: [flipBindingx],
    // #endif
    // #ifdef MP
    components: {
      MpChild,
    },
    // #endif
    props: {
      // #ifdef MP
      // 控制小程序子组件显示，传入组件名称则不使用插槽
      componentName: {
        type: String,
        default: '',
      },
      // #endif
      data: {
        type: Array,
        default() {
          return new Array;
        },
      },
      //自动播放
      autoplay: {
        type: Boolean,
        default: false,
      },
      //自动播放周期
      interval: {
        type: [Number, String],
        default: 5000,
      },
      vertical: {
        type: Boolean,
        default: false,
      },
      current: {
        type: [Number, String],
        default: 0,
      },
      //翻页方式
      type: {
        type: String,
        default: 'real',
      },
      //滑动周期
      duration: {
        type: Number,
        default: 100,
      },
      //容错距离
      sliderFault: {
        type: Number,
        default: 20,
      },
      //背景颜色
      background: {
        type: String,
        default: '#FBF3E1',
      },
      backgroundSize: {
        type: String,
        default: '100% 100%',
      },
      //是否关闭点击左右2侧位置翻页
      unableClickPage: {
        type: Boolean,
        default: false,
      },
      //开启下拉刷新
      pulldownable: {
        type: [Boolean, String],
        default: false,
      },
      //下拉刷新高度
      pulldownHeight: {
        type: [Number, String],
        default: 80,
      },
      //开启上拉加载
      pullupable: {
        type: Boolean,
        default: false,
      },
      //上拉加载高度
      pullupHeight: {
        type: [Number, String],
        default: 80,
      },
    },
    computed: {
      dataSync() {
        let arr = [];
        if (this.prevIndex >= 0) {
          arr.push(this.prevIndex);
        }
        arr.push(this.currentIndex);
        if (this.nextIndex < this.count) {
          arr.push(this.nextIndex);
        }
        return this.refreshing ? [] : arr.sort((a, b) => b - a);
      },
      nextIndex() {
        return this.currentIndex + 1 > this.count - 1 && this.count > 2 ? 0 : this.currentIndex + 1;
      },
      prevIndex() {
        return this.currentIndex - 1 < 0 && this.count > 2 ? this.count - 1 : this.currentIndex - 1;
      },
      count() {
        return this.data.length;
      },
      flipProp() {
        return {
          vertical: this.vertical,
          pulldownable: this.pulldownable,
          pullupable: this.pullupable,
          pulldownHeight: this.pulldownHeight,
          pullupHeight: this.pullupHeight,
          loadingState: this.loadingState,
          duration: this.duration,
          unableClickPage: this.unableClickPage,
          nextIndex: this.nextIndex,
          prevIndex: this.prevIndex,
          currentIndex: this.currentIndex,
          type: this.type,
          count: this.count,
          flipTo: this.flipTo,
          sliderFault: this.sliderFault,
          translate: this.translate,
        };
      },
      pulldownStyle() {
        return this.vertical ? {
          left: 0,
          right: 0,
          top: 0,
          height: this.pulldownHeight + 'px',
          transform: this.translate + '(-' + this.pulldownHeight + 'px)',
        } : {
          left: 0,
          top: 0,
          bottom: 0,
          width: this.pulldownHeight + 'px',
          transform: this.translate + '(-' + this.pulldownHeight + 'px)',
        };
      },
      pullupStyle() {
        return this.vertical ? {
          left: 0,
          right: 0,
          bottom: 0,
          height: this.pullupHeight + 'px',
          transform: this.translate + '(' + this.pullupHeight + 'px)',
        } : {
          right: 0,
          top: 0,
          bottom: 0,
          width: this.pullupHeight + 'px',
          transform: this.translate + '(' + this.pullupHeight + 'px)',
        };
      },
      shadowStyle() {
        return this.vertical ? {
          bottom: 0,
          right: 0,
          left: 0,
          height: 0,
          // #ifdef APP-NVUE
          'background-image': 'linear-gradient(to bottom, rgba(255,255,255, 0), rgba(0,0,0,.5))',
          // #endif
        } : {
          top: 0,
          bottom: 0,
          right: 0,
          width: 0,
          // #ifdef APP-NVUE
          'background-image': 'linear-gradient(to right, rgba(255,255,255, .1), rgba(0,0,0,.3))',
          // #endif
        };
      },
      translate() {
        return this.vertical ? 'translateY' : 'translateX';
      },
      fullSize() {
        return this.vertical ? '3050rpx' : '750rpx';
      },
    },
    data() {
      return {
        refreshing: false,
        currentIndex: 0,
        flipTo: 0,
        loadingState: '',
        updateIndex: null,
      };
    },
    created() {
      this.currentIndex = this.current;
      this.startAutoplay();
    },
    beforeDestroy() {
      this.stopAutoplay();
    },
    methods: {
      getKey(item) {
        // #ifdef APP-VUE
        return this.updateIndex == item ? item + this.data.length : item;
        // #endif
        // #ifndef APP-VUE
        return item;
        // #endif
      },
      forceUpdate(index) {
        this.updateIndex = index;
        this.$nextTick(function() {
          this.updateIndex = null;
        });
      },
      handleFlipChange(value) {
        this.startAutoplay();
        if (value > 0) {
          this.currentIndex = this.currentIndex + value > this.count - 1 ? 0 : this.currentIndex + value;
        } else {
          this.currentIndex = this.currentIndex + value < 0 ? this.count - 1 : this.currentIndex + value;
        }
        this.$emit('change', {
          current: this.currentIndex,
          detail: this.data[this.currentIndex],
        });
        this.$emit('update:current', this.currentIndex);
      },
      pullingRefresh(type) {
        this.$emit(type, (state) => {
          this.loadingState = state;
          // #ifdef APP-NVUE
          this.resetPullingBindingx();
          // #endif
        });
      },
      flipToNext() {
        this.stopAutoplay();
        // #ifdef APP-NVUE
        this.flipToNextBindingX();
        // #endif
        // #ifndef APP-NVUE
        this.flipTo = 0;
        this.$nextTick(function() {
          this.flipTo = 1;
        });
        // #endif
      },
      flipToPrev() {
        this.stopAutoplay();
        // #ifdef APP-NVUE
        this.flipToPrevBindingX();
        // #endif
        // #ifndef APP-NVUE
        this.flipTo = 0;
        this.$nextTick(function() {
          this.flipTo = -1;
        });
        // #endif
      },
      refresh() {
        this.stopAutoplay();
        this.refreshing = true;
        this.$nextTick(function() {
          this.currentIndex = this.current;
          this.refreshing = false;
          this.startAutoplay();
        });
      },
      resetLoading() {
        this.loadingState = '';
        // #ifdef APP-NVUE
        this.resetPullingBindingx();
        // #endif
      },
      startAutoplay() {
        this.stopAutoplay();
        if (this.autoplay) {
          this.autoplayTimer = setTimeout(() => {
            if (this.data.length > 1 && this.current < this.data.length - 1) this.flipToNext();
            else this.startAutoplay();
          }, this.interval);
        }
      },
      stopAutoplay() {
        if (this.autoplayTimer) {
          clearTimeout(this.autoplayTimer);
          this.autoplayTimer = null;
        }
      },
    },
    watch: {
      current(newVal) {
        this.currentIndex = newVal;
      },
      autoplay() {
        this.startAutoplay();
      },
    },
  };
</script>
<!-- #ifdef APP-VUE || H5 || MP-QQ || MP-WEIXIN -->
<script lang="wxs" module="flip" src="./flip.wxs"></script>
<!-- #endif -->
<style scoped>
  .yingbing-flip {
    /* #ifdef APP-NVUE */
    flex: 1;
    /* #endif */
    /* #ifndef APP-NVUE */
    flex: 1;
    /* #endif */
    /* #ifdef MP-WEIXIN */
    height: 100%;
    /* #endif */
    overflow: hidden;
    position: relative;
  }

  .yingbing-flip-item {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    height: 100%;
    /* #ifndef APP-NVUE */
    overflow: hidden;
    /* #endif */
  }

  .yingbing-flip-item-content {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }

  .yingbing-flip-item-bg {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    /* #ifdef APP-NVUE */
    box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.2);
    /* #endif */
  }

  .yingbing-flip-item-shadow {
    position: absolute;
    /* #ifdef APP-NVUE */
    opacity: 0.5;
    /* #endif */
  }

  .yingbing-flip-pulldown, .yingbing-flip-pullup {
    position: absolute;
  }

  .yingbing-flip-pulldown-item, .yingbing-flip-pullup-item {
    /* #ifndef APP-NVUE */
    visibility: hidden;
    /* #endif */
    /* #ifdef APP-NVUE */
    opacity: 0;
    /* #endif */
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }

  /* #ifdef MP */
  /deep/ .scoped-ref {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  }

  /deep/ yingbing-flip {
    display: block;
    height: 100%;
  }

  /* #endif */
</style>
